/*
	The Raja Toolkit.
	Copyright (C) 2011 Raja-Toolkit Foundation

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 3.0 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "types.hpp"

namespace raja
{

const uint32 INITIAL_REAL_SIZE	= 4;

element_array::element_array(uint32 elem_size) : __elem_size(elem_size), __data(0), __count(0), __real_size(INITIAL_REAL_SIZE)
{
	__data	= malloc(elem_size * __real_size);
	assert(__data != 0);
}

element_array::~element_array()
{
	std::cout << "~element_array" << std::endl;
	free(__data);
}

void element_array::resize(uint32 count)
{
	__data	= realloc(__data, count * __elem_size);
	assert( __data != NULL );
	__real_size	= count;
	__count		= count;//std::min(__count, count);
}

void* element_array::push_back(const void* elem)
{
	if( __count == __real_size )
	{
		__real_size	<<= 1;
		std::cout << "reserve now " << __real_size << std::endl;
		__data	= realloc(__data, __elem_size * __real_size);
		assert(__data != 0);
	}

	uint8*		data	= &((static_cast<uint8*>(__data))[(__count++) * __elem_size]);
	memcpy(data, elem, __elem_size);
	return data;
}

void* element_array::pop_back()
{
	assert( __count > 0 );
	uint8*		data	= &((static_cast<uint8*>(__data))[(--__count) * __elem_size]);
	// the element is still in memory, just send a pointer to it
	return data;
}

const void* element_array::operator[](uint32 idx) const
{
	//std::cout << "const void* [] const" << std::endl;
	assert( __count > idx );
	uint8*		data	= &((static_cast<uint8*>(__data))[idx * __elem_size]);
	// the element is still in memory, just send a pointer to it
	return data;
}

void* element_array::operator[](uint32 idx)
{
	//std::cout << "void* []" << std::endl;
	assert( __count > idx );
	uint8*		data	= &((static_cast<uint8*>(__data))[idx * __elem_size]);
	// the element is still in memory, just send a pointer to it
	return data;
}


uint32 element_array::get_count() const
{
	return __count;
}

void* element_array::push_multiple(const void* elems, uint32 count)
{
	if( (__count + count) > __real_size )
	{
		for( ; __real_size < __count + count; __real_size <<= 1 );

		std::cout << "new size: " << __real_size << std::endl;

		__data	= realloc(__data, __real_size * __elem_size);
		assert( __data != NULL );
	}

	uint8*		data	= &((static_cast<uint8*>(__data))[__count * __elem_size]);
	memcpy(data, elems, __elem_size * count);
	__count += count;

	std::cout << "count: " << __count << std::endl;

	return data;
}

}	// namespace raja
